package crawler;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TianYanChaCrawler {
    private static final String SEARCH_URL = "https://www.tianyancha.com/search?key=";
    private static final String COMPANY_DETAIL_URL = "https://www.tianyancha.com/company/";

    private Map<String, String> headers() {
        Map<String, String> headers = new HashMap<>();
        headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36");
        return headers;
    }

    public void searchAndGetDetail(String companyName) {
        try {
            String finalSearchUrl = SEARCH_URL + URLEncoder.encode(companyName, "UTF-8");

            Document doc = Jsoup.connect(finalSearchUrl)
                    .headers(headers())
                    .get();

            // 获取搜索结果
            List<CompanyItem> searchItemList = buildSearchItemList(doc.select("div.search-block div.result-list div.search-item"));
            System.out.println("搜索结果为: " + searchItemList);

            // 在结果中寻找最匹配的公司
            CompanyItem bestMatcher = bestMatched(companyName, searchItemList);

            // 转到具体公司详细信息
            Document companyDetailDoc = Jsoup.connect(COMPANY_DETAIL_URL + bestMatcher.companyId)
                    .headers(headers())
                    .get();

            CompanyItem companyDetail = buildCompanyDetail(companyDetailDoc);
            System.out.println("公司详细结果为: " + companyDetail);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private CompanyItem buildCompanyDetail(Document companyDetailDoc) {
        CompanyItem detail = new CompanyItem();

        // 获取公司名
        String companyName = null;
        companyName = companyDetailDoc.selectFirst("#company_web_top div.header .name").ownText();
        detail.setCompanyName(companyName);

        // 获取法人名
        String legalPersonName = null;
        Element legalPersonNameDoc = companyDetailDoc.selectFirst("div.detail-list  #_container_baseInfo .name a");
        if (legalPersonNameDoc != null) {
            legalPersonName = legalPersonNameDoc.ownText();
        }
        detail.setLegalPersonName(legalPersonName);

        // 获取评分
        String score = null;
        Element scoreDoc = companyDetailDoc.selectFirst("div.detail-list  #_container_baseInfo .sort-chart");
        if (scoreDoc != null) {
            score = scoreDoc.attr("alt");
        }
        detail.setScore(score);

        // 获取公司地址
        String address = null;
        // style1
        Element addressDoc = companyDetailDoc.selectFirst("#company_web_top div.content .address");
        if (addressDoc != null) {
            address = addressDoc.attr("title");
        }
        // style2
        if (address == null || "".equals(address)) {
            Elements labels = companyDetailDoc.select("#company_web_top .label");
            if (labels != null) {
                for (Element label : labels) {
                    if (label.text().contains("地址")) {
                        address = label.parent().ownText();
                        break;
                    }
                }
            }
        }
        detail.setAddress(address);

        return detail;
    }

    private CompanyItem bestMatched(String companyName, List<CompanyItem> searchItemList) {
        int bestMatcherIndex = -1;
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < searchItemList.size(); i++) {
            CompanyItem searchItem = searchItemList.get(i);
            int matched = matchedChars(companyName, searchItem.companyName);
            if (matched == companyName.length()) {
                bestMatcherIndex = i;
                break;
            }
            if (max < matched) {
                max = matched;
                bestMatcherIndex = i;
            }
        }
        if (bestMatcherIndex < 0) {
            throw new RuntimeException("查无此公司,可能改名");
        }
        return searchItemList.get(bestMatcherIndex);
    }

    private int matchedChars(String companyName, String otherCompanyName) {
        if (companyName.equals(otherCompanyName)) {
            return companyName.length();
        } else {
            int equalsCharNumber = 0;
            // 查询相同字符串
            for (int i = 0; i < companyName.length(); i++) {
                char c = companyName.charAt(i);
                if (otherCompanyName.indexOf(c) != -1) {
                    equalsCharNumber++;
                }
            }
            return equalsCharNumber;
        }
    }

    private List<CompanyItem> buildSearchItemList(Elements searchItemList) {
        List<CompanyItem> result = new ArrayList<>();
        for (Element searchItem : searchItemList) {
            result.add(buildSearchItem(searchItem));
        }
        return result;
    }

    private CompanyItem buildSearchItem(Element searchItem) {
        // 获取公司编号
        String companyId = searchItem.selectFirst("div.search-result-single").attr("data-id");
        String companyName = searchItem.selectFirst("div.search-result-single .img").attr("alt");
        // 去除html标签
        companyName = pureHtmlTag(companyName);

        CompanyItem companyItem = new CompanyItem();
        companyItem.setCompanyId(companyId)
                .setCompanyName(companyName);
        return companyItem;
    }

    /**
     * 去除html标签
     *
     * @param companyName
     * @return
     */
    private String pureHtmlTag(String companyName) {
        // 定义HTML标签的正则表达式
        String regEx_html = "<[^>]+>";
        String regEx_html1 = "<[^>]+";

        return companyName.replaceAll(regEx_html, "")
                .replaceAll(regEx_html1, "");
    }

    /**
     * 需要的属性自己添加
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Accessors(chain = true)
    class CompanyItem {
        // 公司编号
        String companyId;

        // 法人名
        String legalPersonName;

        // 公司名字
        String companyName;

        // 公司地址
        String address;

        // 公司评分
        String score;
    }
}
